package com.me.libgdx_test;

import java.io.File;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.assets.AssetManager;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.FPSLogger;
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.Texture.TextureFilter;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer.ShapeType;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.utils.Drawable;
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;

public class ActivityGame implements Screen, InputProcessor {
	private OrthographicCamera camera;
	private SpriteBatch world, hud;
	private ClassLogDisplay logger;
	private ClassBoardHolder board;
	private Touch touch;
	private BitmapFont font;
	private float base_font_size;
	private ClassCustomFPSLogger fps_log;
	ShapeRenderer shaperenderer = new ShapeRenderer();
	private boolean dirty_handler;
	
	//Pinch zoom stuff
	private int numberOfFingers = 0;
	private int fingerOnePointer;
	private int fingerTwoPointer;
	private float lastDistance = 0;
	private Vector3 fingerOne = new Vector3();
	private Vector3 fingerTwo = new Vector3();
	private Vector3 frustum_vector = new Vector3();
	private Sprite background;
	private Color background_color;
	private Stage stage;
	
	ActivityMain game;

	public ActivityGame(ActivityMain game) {	
		this.game = game;
		stage = new Stage();
		Texture.setEnforcePotImages(false);
		logger = new ClassLogDisplay("Activity Main");
		fps_log = new ClassCustomFPSLogger();
		logger.print(String.valueOf(Gdx.graphics.getWidth()) + "x" + String.valueOf(Gdx.graphics.getHeight()));
		touch = new Touch();
		Point board_size = new Point(20,20);
		board = new ClassBoardHolder(board_size, new Point(Gdx.graphics.getWidth(),Gdx.graphics.getHeight()),game.game_vars, game.sprite_textures, stage, game.skin);
		dirty_handler = true;
		float w = Gdx.graphics.getWidth();
		float h = Gdx.graphics.getHeight();
		//Gdx.graphics.setContinuousRendering(false);
		//Gdx.graphics.requestRendering();
		camera = new OrthographicCamera(w, h);
		camera.zoom = 0.4f;
		world = new SpriteBatch();
		hud = new SpriteBatch();
		font = new BitmapFont();
		base_font_size = 12;
		Texture texture = new Texture("data/game_background.png");
		background_color = new Color(.5f,.5f,.5f, 1f);
		
		texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
		 
	   background = new Sprite(texture);
	   calculate_background();
	}

	@Override
	public void dispose() {
		world.dispose();
	}

	@Override
	public void render(float delta) {	
			Gdx.gl.glClearColor(1, 1, 1, 1);
			Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
			
			fps_log.setClickLatency();
			
			//If there are currently animations in the buffer we need to 
			//make sure that they are played before the thread rests
			if(board.has_current_animations()){
				//logger.print("Resetting Board");
				board.reset_board();
			}
			
			if (dirty_handler){
				camera.position.set(board.get_refined_position().x,board.get_refined_position().y,0);
				dirty_handler = !dirty_handler;
			}
			dirty_handler = board.just_moved();

			camera.update();
			world.setProjectionMatrix(camera.combined);
			world.begin();

			//background.draw(world);
			
			for(int i = 0; i < board.get_pool().get_pool().length;i++){
				if (board.get_pool().get_pool()[i].get_using()){
					//frustum_vector.set(board.get_pool().get_pool()[i].get_sprite().getX(), board.get_pool().get_pool()[i].get_sprite().getY(), 0);
					//if(camera.frustum.pointInFrustum(frustum_vector)){
					board.get_pool().get_pool()[i].get_sprite().draw(world);
					//}
				}else{
					//logger.print("No more sprites");
					//ClassLogDisplay.print(i);
					break;
				}
			}
			
			for(ClassAnimationString text_object: board.get_text_animations()){
				//font.
				ClassHudText text = text_object.get_animation_frame();
				font.setScale((float) text.get_font_size()/base_font_size, (float) text.get_font_size()/base_font_size);
				font.setColor(text.get_color());
				font.draw(world, text.get_message(), text.get_location().x, text.get_location().y);
				if(text_object.animation_over()){
					board.get_text_animations().remove(text_object);
				}
			}
			
			//get_text_animations()
			/*for(int y = 0; y < board.get_dimensions().y; y++) {
				for(int x = 0; x < board.get_dimensions().x; x++) {
					for(Sprite sprite: board.get_board()[x][y].get_stack()){
						sprite.draw(world);
					}
				}
			}*/
			
			world.end();
			hud.begin();
			/*
			 * ClassSpriteObject sprite: board.get_hud_pool().get_pool()
			 */
			//for(Sprite sprite: board.get_hud().get_stack()){
			for(ClassSpriteObject sprite: board.get_hud_pool().get_pool()){
				if(sprite.get_using()){
					sprite.get_sprite().draw(hud);
				}
			}
			hud.end();
			//This prints the health, mana, and exp bars for the hud
			for(ClassRectangle rectangle: board.get_hud_object().get_rectangles()){
				shaperenderer.begin(ShapeType.Filled);
				shaperenderer.setColor(rectangle.color.x, rectangle.color.y, rectangle.color.z, 1);
				shaperenderer.rect(rectangle.edge.x, rectangle.edge.y, rectangle.dimension.x, rectangle.dimension.y);
				shaperenderer.end();
			}
			hud.begin();
			for(ClassHudText text: board.get_hud_object().get_hud_text()){
				//font.
				font.setScale((float) text.get_font_size()/base_font_size, (float) text.get_font_size()/base_font_size);
				font.setColor(text.get_color());
				font.draw(hud, text.get_message(), text.get_location().x, text.get_location().y);
			}
			
			//This prints all the logging stuff. uncomment to turn it back on
			//font.draw(hud, fps_log.getFPS(), 720, 180);
			//font.draw(hud, fps_log.getClickLatency(), 720, 160);
			//font.draw(hud, fps_log.getClickRenderLatency(), 720, 140);
			//fps_log.getFPS();
			
			hud.end();
			if (board.get_player_object().check_for_death() || board.get_bosses()<1){

				game.endScreen = new ActivityEndScreen(game,board.get_player_object().calculateScore(board));
				game.setScreen(game.endScreen);
			}
			
			stage.act(Math.min(Gdx.graphics.getDeltaTime(), 1 / 30f));
			stage.draw();
	}

	@Override
	public void resize(int width, int height) {
		
	}

	@Override
	public void pause() {
		 numberOfFingers = 0;
	}

	@Override
	public void resume() {
	}
	
	@Override
    public boolean touchDown(int screenX, int screenY, int pointer, int button) {
		logger.print("Touch_Down");
		// for pinch-to-zoom
		 numberOfFingers++;
		 if(numberOfFingers == 1)
		 {
			Vector3 click = new Vector3(screenX,screenY,0);
			fingerOne = new Vector3(click);
			fingerOnePointer = pointer;
			
			if(pointer < 5){
				fps_log.click();
				logger.print("Primary Touch Pointer");
				logger.print("Touch at");
				logger.print(click);
	        	camera.unproject(click);
	        	touch.set_finger_down(new Point(screenX,screenY),new Point((int)click.x,(int)click.y), true);
	        	dirty_handler = true;
	        	board.push_touch(touch);
			}
		 }
		 else if(numberOfFingers == 2)
		 {
	        fingerTwoPointer = pointer;
	        fingerTwo.set(new Vector3(screenX,screenY,0));
	 
	        float distance = fingerOne.dst(fingerTwo);
	        lastDistance = distance;
		 }
        /*if(pointer < 5){
        	logger.print("Alternate Touch Pointer");
        	Vector3 click = new Vector3(screenX,screenY,0);
        	camera.unproject(click);
        	touch.set_finger_down(new Point(screenX,screenY),new Point((int)click.x,(int)click.y), true);
        	dirty_handler = true;
        	board.push_touch(touch);
        }*/
        return true;
    }

    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
    	logger.print("Touch_Up");
        if(pointer < 5){
        	//touch.set_finger_down(new Point(screenX,screenY), false);
        	 if(numberOfFingers == 1)
        	 {
        	        Vector3 touchPoint = new Vector3(screenX, screenY, 0);
        	        camera.unproject(touchPoint);
        	 }
        	 numberOfFingers--;
        	 
        	// just some error prevention... clamping number of fingers (ouch! :-)
        	 if(numberOfFingers<0){
        	        numberOfFingers = 0;
        	 }
        	lastDistance = 0;
        }
        return true;
    }

	@Override
	public boolean keyDown(int keycode) {
		if(Keys.A == keycode) {
            camera.zoom += 0.1;
            ClassLogDisplay.print(camera.zoom);
            //calculate_background();
	    }
	    if(Keys.Q == keycode) {
	    	camera.zoom -= 0.1;
	    	ClassLogDisplay.print(camera.zoom);
	    	//calculate_background();
	    }
	    if(Keys.LEFT == keycode) {
	            if (camera.position.x > 0)
	            	camera.translate(-10, 0, 0);
	    }
	    if(Keys.RIGHT == keycode) {
	            if (camera.position.x < 1024)
	            	camera.translate(10, 0, 0);
	    }
	    if(Keys.DOWN == keycode) {
	            if (camera.position.y > 0)
	            	camera.translate(0, -10, 0);
	    }
	    if(Keys.UP == keycode) {
	            if (camera.position.y < 1024)
	            	camera.translate(0, 10, 0);
		}
	    
	    if (camera.zoom < .2f) camera.zoom = .2f;
		if (camera.zoom > 2f) camera.zoom = 2f;
	    
		return false;
	}

	@Override
	public boolean keyUp(int keycode) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean keyTyped(char character) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean touchDragged(int screenX, int screenY, int pointer) {
		// for pinch-to-zoom
		if(numberOfFingers == 2){
			 if (pointer == fingerOnePointer) {
			        fingerOne.set(screenX, screenY, 0);
			 }
			 if (pointer == fingerTwoPointer) {
			        fingerTwo.set(screenX, screenY, 0);
			 }
			 
			float distance = fingerOne.dst(fingerTwo);
			float factor = distance / lastDistance / 100;
			 
			logger.print("Touch Dragged");
			logger.print(camera.zoom);
			
			if (lastDistance > distance) {
				camera.zoom += factor;
			 } else if (lastDistance < distance) {
				 camera.zoom -= factor;
			 }
			 
	
			// clamps field of view to common angles...
			 if (camera.zoom < .2f) camera.zoom = .2f;
			 if (camera.zoom > 2f) camera.zoom = 2f;
			 
	
			lastDistance = distance;
		}
		//camera.update();
		//camera.apply(Gdx);
		return false;
	}
	
	private void calculate_background(){
		//float width = camera.zoom * camera.viewportWidth;
		//float height = camera.zoom * camera.viewportHeight;
		float w = Gdx.graphics.getWidth()*4;
		float h = Gdx.graphics.getHeight()*4;
		background.setOrigin(0,0);
		background.setSize(w,h);
		background.setPosition(- w/2,0);
	}

	@Override
	public boolean mouseMoved(int screenX, int screenY) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean scrolled(int amount) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void show() {
		Gdx.input.setInputProcessor(this);
		// TODO Auto-generated method stub
		
	}

	@Override
	public void hide() {
		// TODO Auto-generated method stub
		
	}
}
